

/*
** client.c -- a stream socket client demo
*/

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>


#define PORT 3490    /* the port client will be connecting to */

#define MAXDATASIZE 100 /* max number of bytes we can get at once */

typedef struct _stat_{
	int* data;
	int* meta;
	char** labels;
} statCounters;

void updateCounters(statCounters* stat, int numChar, int numLines);
void printExecStat(statCounters stat);
void initStatCounters(statCounters* s);
void delCounters(statCounters* s);

int main(int argc, char *argv[])
{
    int sockfd;

    struct hostent *he;
    struct sockaddr_in their_addr; /* connector's address information */

    if (argc != 2) {
        fprintf(stderr,"usage: client hostname\n");
        exit(1);
    }

    if ((he=gethostbyname(argv[1])) == NULL) {  /* get the host info */
        perror("gethostbyname");
        exit(1);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    their_addr.sin_family = AF_INET;         /* host byte order */
    their_addr.sin_port = htons(PORT);     /* short, network byte order */
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);        /* zero the rest of the struct */

    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
        perror("connect");
        exit(1);
    }


    //Statistics counters
    statCounters recvCounter;
    statCounters sendCounter;

    initStatCounters(&recvCounter);
    initStatCounters(&sendCounter);

    int numbytes;
    char buf[MAXDATASIZE];

    /*
     *	Start to count time from here
     */

    /*
     * Get lines from file, send them to the server, wait for the server reply printing to stdout in each stage.
     */
    while(!feof(stdin)){

    	fgets(buf, MAXDATASIZE, stdin);

    	if((numbytes = write(sockfd, buf, strlen(buf))) < 0){
    		printf("Error sending data to the server.");
    	}
    	else{
    		printf("Client: Line sent to server: %s\n", buf);
    		updateCounters(&sendCounter, numbytes, 1);
    	}

    	if((numbytes = recv(sockfd, buf, MAXDATASIZE, 0)) < 0){
    		printf("Error reading data sent back from server.");
    	}
    	else{
    		buf[numbytes] = '\0';
    		printf("Client: Line received from server: %s\n", buf);
    		updateCounters(&recvCounter, numbytes, 1);
    	}

    	//remove trailing control characters from the stream.
    	char c;
    	while(isspace(c = fgetc(stdin)));
    	ungetc(c, stdin);
    }

    close(sockfd);

    /*
     * 	End time count.
     */

    char* labels[3] = {"Total lines received",
    				"Longest line in chars",
    				"Total chars received"};

    int display[3] = {1, 1, 1};

    recvCounter.labels = labels;
    recvCounter.meta = display;

    printExecStat(recvCounter);
    fprintf(stderr, "**************\n");

    labels[0] = "Total lines sent";
    labels[1] = "Longest line in chars";
    labels[2] = "Total chars sent";

//    display[1] = 0;

    sendCounter.labels = labels;
    sendCounter.meta = display;

    printExecStat(sendCounter);

    //Time spent info -> stderr


    delCounters(&recvCounter);
    delCounters(&sendCounter);



    return 0;
}

void updateCounters(statCounters* stat, int numChar, int numLines){
	if(stat->data[1] < numChar){
		stat->data[1] = numChar;
	}

	stat->data[2] += numChar;
	stat->data[0] += numLines;
}

void printExecStat(statCounters stat){
	int i;
	for(i = 0; i < 3; i++){
		if(stat.meta[i]){
			fprintf(stderr, "%s: %d\n", stat.labels[i], stat.data[i]);
		}
	}
}

void initStatCounters(statCounters* s){
	int i;
	s->data = malloc(3*sizeof(int));

	for(i = 0; i < 3; i++){
		s->data[i] = 0;
	}
}

void delCounters(statCounters* s){
	free(s->data);
}



